package com.zmkj.cn.comm.util;


import com.google.common.collect.Maps;
import com.zmkj.cn.comm.baseenum.SeparatorEnum;
import org.springframework.cglib.beans.BeanMap;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;


public class CoyAttrUtils {
    private static void quotationVaild(StringBuilder endStr, Object appendStr, Boolean quotation) {
        if (quotation) {
            endStr.append("'");
        }
        endStr.append(appendStr);
        if (quotation) {
            endStr.append("'");
        }
        endStr.append(",");
    }

    public static String getFieldStrByList(List<?> objList, String field, int type, boolean quotation) {
        if (objList == null || objList.size() == 0) {
            return "";
        }
        StringBuilder endStr = new StringBuilder();
        switch (type) {
            case 1:
                String thisField = "get" + field.substring(0, 1).toUpperCase() + field.substring(1);
                objList.forEach(obj -> {
                    try {
                        Method method = obj.getClass().getMethod(thisField);
                        Object objs = method.invoke(obj);
                        quotationVaild(endStr, objs, quotation);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
                break;
            case 2:
                objList.forEach(obj -> quotationVaild(endStr, obj, quotation));
                break;
            case 3:
                objList.forEach(obj -> {
                    HashMap mapObj = (HashMap) obj;
                    quotationVaild(endStr, mapObj.get(field), quotation);
                });
                break;
            default:
                break;
        }
        if (endStr.length() > 0) {
            return endStr.substring(0, endStr.length() - 1);
        }
        return endStr.toString();
    }

    public static Map<String, Object> filterDic(List<Map<String, Object>> resultMap, String params) {
        return filterDic(resultMap, "value", params);
    }

    public static Map<String, Object> filterDic(List<Map<String, Object>> resultMap, String type, String params) {
        Optional<Map<String, Object>> optional = resultMap.stream().filter(dicMap -> dicMap.get(type).toString().equals(params)).findAny();
        return optional.orElse(null);
    }

    public static List<List<?>> cutList(List<?> resultMap, Integer maxNumber) {
        return Stream.iterate(0, n -> n + 1).limit((resultMap.size() + maxNumber - 1) / maxNumber).parallel().map(a -> resultMap.stream().skip(a * maxNumber).limit(maxNumber).parallel().collect(Collectors.toList())).collect(Collectors.toList());
    }

    public static String addEdition(String oldEdition, int... maxRules) {
        String[] oldEditionLis = oldEdition.split("\\.");
        for (int i = oldEditionLis.length - 1; i >= 0; i--) {
            oldEditionLis[i] = (Integer.parseInt(oldEditionLis[i]) + 1) + "";
            int index = i + maxRules.length - oldEditionLis.length;
            if (index != -1 && Integer.parseInt(oldEditionLis[i]) == maxRules[index]) {
                oldEditionLis[i] = 0 + "";
                continue;
            }
            break;
        }
        return getFieldStrByList(Arrays.asList(oldEditionLis), false).replace(",", SeparatorEnum.SPOT.code);
    }

    public static Map<String, String[]> transListToMapArray(List<Map<String, Object>> list, String[] titles) {
        Map<String, String[]> map = new HashMap<>(titles.length);
        for (int i = 0; i < titles.length; i++) {
            String[] temp = new String[list.size()];
            map.put(titles[i], temp);
        }
        for (int k = 0; k < list.size(); k++) {
            for (int i = 0; i < titles.length; i++) {
                map.get(titles[i])[k] = (list.get(k).get(titles[i])).toString();
            }
        }
        return map;
    }

    private final static ThreadLocal<SimpleDateFormat> SIMPLE_DATE_TEMP = new ThreadLocal<>();


    public static void removeSimpleDateFormat() {
        SIMPLE_DATE_TEMP.remove();
    }


    public static String getFieldStrByList(List<?> objList) {
        return getFieldStrByList(objList, null, 2, true);
    }

    public static String getFieldStrByList(List<?> objList, boolean quotation) {
        return getFieldStrByList(objList, null, 2, quotation);
    }

    public static String getFieldStrByList(List<?> objList, String field) {
        return getFieldStrByList(objList, field, 1, true);
    }

    public static String getFieldStrByList(List<?> objList, String field, boolean quotation) {
        return getFieldStrByList(objList, field, 1, quotation);
    }

    public static String getFieldStrByList(String[] list) {
        StringBuilder str = new StringBuilder();
        for (String data : list) {
            str.append(",'").append(data).append("'");
        }
        return str.length() > 0 ? str.substring(1) : null;
    }

    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

//    @Test
//    public void transByRuleTest(){
//        // 把 999999分钟转换成 天结算
//        System.out.println(timeStrToInt(999999.0,"分钟","天"));
//    }
//    private Integer timeStrToInt(Double reData,String ruleType,String needRule){
//        // 规则单位
//        String[] timeRules = {"分钟","小时","天","星期","月","年"};
//        // 规则进位规则
//        Double[] ransRules = {60.0,24.0,7.0,4.35,12.0};
//        Double data = CoyUtils.transByRule(timeRules, ransRules, reData, ruleType, needRule);
//        return data.intValue();
//    }

    public static Double transByRule(String[] rules, Double[] ruleTrans, Double source, String ruleType, String needRule) {
        if (ruleType == null || needRule == null) {
            return null;
        }
        if (ruleType.equals(needRule)) {
            return source;
        }
        int flagIndex = -1;
        int needIndex = -1;
        for (int i = 0; i < rules.length; i++) {
            if (flagIndex == -1 && ruleType.equals(rules[i])) {
                flagIndex = i;
            }
            if (needIndex == -1 && needRule.equals(rules[i])) {
                needIndex = i;
            }
        }
        // 不识别转换
        if (flagIndex == -1 || needIndex == -1) {
            return null;
        }
        if (flagIndex < needIndex) {
            // 低位升高位
            for (int i = flagIndex; i < needIndex; i++) {
                source = source / ruleTrans[i];
            }
        } else {
            // 高位降低位
            for (int i = flagIndex; i > needIndex; i--) {
                source = source * ruleTrans[i - 1];
            }
        }
        return source;
    }

    public static boolean createParentPath(File file) {
        File parentFile = file.getParentFile();
        boolean mkdirs = false;
        if (null != parentFile && !parentFile.exists()) {
            mkdirs = parentFile.mkdirs();
            createParentPath(parentFile);
        }
        return mkdirs;
    }


    public static boolean notNullEquals(String someData, String otherData) {
        if (someData == null || otherData == null) {
            return false;
        }
        return someData.equals(otherData);
    }

    private static final Pattern PATTERN_IS_INTEGER = Pattern.compile("^[-+]?[\\d]*$");

    public static boolean isInteger(String str) {
        return PATTERN_IS_INTEGER.matcher(str).matches();
    }

    public static String getSuffix(String name) {
        return name.substring(name.lastIndexOf(SeparatorEnum.SPOT.code) + 1).toLowerCase();
    }

    /**
     * 自己写的, 因为用到了异步, 感觉有点点问题, 以后再优化
     *
     * @return 树状结构目录
     * @Description: 根据文件列表生成响应的层级结构
     * @author 伍绍宇 Coy
     * @date 2021年2月4日 12:17:57
     */
    public static Map<String, Object> layeredList(List<Map<String, Object>> sourceList, String flag, String childrenStr, String division) {
        Map<String, Object> backList = new HashMap<>(3);
        backList.put("name", "初始目录");
        backList.put("id", System.currentTimeMillis() + "");
        backList.put(childrenStr, new ArrayList<Map<String, Object>>());
        sourceList.parallelStream().forEach(source -> {
            // 获取父目录
            List<Map<String, Object>> dirList = getDirList(backList, source.get(flag).toString(), childrenStr, division);
            dirList.add(source);
        });
        return backList;
    }

    private static List<Map<String, Object>> getDirList(Map<String, Object> backList, String dir, String childrenStr, String division) {
        String[] dirArr = dir.split(division);
        Map<String, Object> dirLook = createDir(backList, dirArr[0], childrenStr);
        if (dirArr.length > 1) {
            // 没有到最里层
            return getDirList(dirLook, dir.substring(dir.indexOf(division) + 1), childrenStr, division);
        }
        return (List<Map<String, Object>>) dirLook.get(childrenStr);
    }

    private static Map<String, Object> createDir(Map<String, Object> dir, String dirName, String childrenStr) {
        List<Map<String, Object>> maps = (List<Map<String, Object>>) dir.get(childrenStr);
        Map<String, Object> endMap = new HashMap<>(2);
        boolean isCreateMap = true;
        // 判断子文件是否存在文件夹
        for (Map<String, Object> childMap : maps) {
            if (childMap.get("name").equals(dirName)) {
                // 如果有的话,直接获取
                endMap = childMap;
                isCreateMap = false;
                break;
            }
        }
        // 没有文件夹就创建
        if (isCreateMap) {
            endMap.put("name", dirName);
            endMap.put("id", System.currentTimeMillis() + dirName);
            endMap.put(childrenStr, new ArrayList<Map<String, Object>>());
            maps.add(endMap);
        }
        return endMap;
    }

    /**
     * 首字母大写
     *
     * @param string
     * 
     */
    public static String toUpperCase4Index(String string) {
        char[] methodName = string.toCharArray();
        methodName[0] = toUpperCase(methodName[0]);
        return String.valueOf(methodName);
    }

    /**
     * 字符转成大写
     *
     * @param chars
     * 
     */
    public static char toUpperCase(char chars) {
        if (97 <= chars && chars <= 122) {
            chars ^= 32;
        }
        return chars;
    }

    public static <T> Map<String, Object> beanToMap(T bean) {
        Map<String, Object> map = Maps.newHashMap();
        if (bean != null) {
            BeanMap beanMap = BeanMap.create(bean);
            for (Object key : beanMap.keySet()) {
                map.put(key + "", beanMap.get(key));
            }
        }
        return map;
    }

//    public int[] getAllIds(Integer id) {
//        // 通过ID获取部门信息
//        Map<String, Object> deptList = filterDic(InitDataListener.deptList, "id", id.toString());
//        String deptNo = deptList.get("dept_no").toString();
//        int baseLength = 3;
//        List<Integer> arr = new ArrayList();
//        do {
//            Map<String, Object> dept = filterDic(InitDataListener.deptList, "dept_no", deptNo);
//            arr.add(Integer.parseInt(dept.get("id").toString()));
//            deptNo = deptNo.substring(0,deptNo.length() -2);
//        } while (deptNo.length() > baseLength);
//        Collections.reverse(arr);
//        return arr.toArray();
//    }
}
